package com.taichuan.selfcheck.hardware;

import android.util.Log;

import com.a64.a64board.TcA64GpioClient;
import com.g3288.g3288board.Rk3399GpioActionDefine;
import com.g3288.g3288board.TcRk3399GpioClient;
import com.taichuan.selfcheck.config.PropertyDefaultValue;
import com.taichuan.selfcheck.config.PropertyKey;
import com.taichuan.selfcheck.config.PropertyPreference;
import com.taichuan.selfcheck.utils.HardwareUtils;
import com.taichuan.selfcheck.utils.LightTimeUtils;
import com.taichuan.serialcommunication.SerialPortPublic;
import com.taichuan.tcutils.taichuan.SystemUtils;
import com.taichuan.tcutils.taichuan.TcDeviceType;

import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 该类主要用于 进行A33设备/A64 设备的补光灯控制
 *
 * @author CamelLuo
 * @version 2019/12/10
 */
public class LightControlUtils {
    private static final String TAG = LightControlUtils.class.getSimpleName();
    private int currentLightValue;

    /**
     * 定义一个原子变量 用于控制是否在获取到光感值后打开补光灯
     * 防止多线程操作可能导致的同步问题
     */
    private AtomicBoolean isOpenFillLightAfterGetLightPowerValue = new AtomicBoolean(false);

    private static LightControlUtils sInstance;

    private LightControlUtils() {
        //获取当前设备的设备型号
        TcDeviceType tcDeviceType = SystemUtils.getTcDeviceType();
    }

    public static LightControlUtils getInstance() {
        if (sInstance == null) {
            synchronized (LightControlUtils.class) {
                if (sInstance == null) {
                    sInstance = new LightControlUtils();
                }
            }
        }
        return sInstance;
    }

    /**
     * 定义一个方法用于开启或关闭红外灯
     */
    public void openOrCloseInfraredLight(boolean isOpen) {
        if (SystemUtils.isRk3399()) {
            if (SystemUtils.getTcDeviceType() == TcDeviceType.RK3399_LANDSCAPE_KEY || HardwareUtils.is20Devices() ||
            SystemUtils.isVankeSiteBoxDevice()) {
                SerialPortPublic.controlInfrardLight(isOpen);
            } else {
                if (isOpen) {
                    //开启红外灯
                    TcRk3399GpioClient.getInstance().controlGpio(Rk3399GpioActionDefine.CONTROL_INFRAED_LIGHT_OPEN);
                } else {
                    //关闭红外灯
                    TcRk3399GpioClient.getInstance().controlGpio(Rk3399GpioActionDefine.CONTROL_INFRAED_LIGHT_CLOSE);
                }
            }

        }
    }

    /**
     * 定义一个方法用于开启或关闭 提示灯
     * 目前只有 Tc-Y9D-O8A设备拥有提示灯
     */
    public void openOrClosePromptLight(boolean isOpen) {
        if (SystemUtils.isRk3399()) {
            if (SystemUtils.getTcDeviceType() == TcDeviceType.RK3399_VERTICAL_TOUCH_O8A_DOOR){
                SerialPortPublic.controlPromptLight(isOpen);
            }
        }else if (SystemUtils.isA64()){
            if (SystemUtils.getTcDeviceType() == TcDeviceType.A64_VERTICAL_TOUCH_HZ01){
                SerialPortPublic.controlPromptLight(isOpen);
            }
        }
    }

    /**
     * 定义一个方法用于设置补光灯的开和关
     *
     * @param isOpen                    开启或关闭补光灯
     * @param isCheckLightConfigCanOpen 开启补光灯前是否需要检测设备的灯光配置
     *                                  *                                  （补光灯是否在开启时间段内以及光感数值是否在设定范围内）
     */
    public void controlFillLight(boolean isOpen, boolean isCheckLightConfigCanOpen) {
        if (isOpen) {
            //根据传入的配置决定是否检测补光灯是否在开启时间段以及光感数值是否在设定范围内
            if (isCheckLightConfigCanOpen) {
                //获取设备是否开启了光感阈值配置和开启时间段配置
                //光感阈值只有在rk3399设备下才拥有，所以非3399设备默认为没有该配置
                boolean isOpenLightModuleValueConfig = false;
                if (SystemUtils.isRk3399()) {
                    isOpenLightModuleValueConfig = isOpenFillLightInLightModuleValueConfig();
                }
                boolean isOpenTimePeriodConfig = isOpenFillLightInTimePeriodConfig();

                //如果设备同时开启了 光感阈值配置 和 时间段配置
                if (isOpenLightModuleValueConfig && isOpenTimePeriodConfig) {
                    if (checkFillLightInTimePeriod()) {
                        Log.i(TAG, "开始执行 开启补光灯开启流程，本次开启 在配置时间段内，无需获取光感阈值，直接开启");
                        //开启补光灯
                        controlFillLightByDevice(true);
                    } else {
                        Log.i(TAG, "开始执行 开启补光灯开启流程，本次开启 不在配置时间段内，需要检测光感配置");
                        //改变标志位为true，当获取感光值后执行开灯操作
                        getLightPowerValueForOpenFillLight();
                    }
                } else if (isOpenLightModuleValueConfig) {
                    Log.i(TAG, "开始执行 开启补光灯开启流程，本次需要检测光感配置");
                    getLightPowerValueForOpenFillLight();
                } else if (isOpenTimePeriodConfig) {
                    if (checkFillLightInTimePeriod()) {
                        Log.i(TAG, "开始执行 开启补光灯开启流程，本次开启 在配置时间段内，开启补光灯");
                        //开启补光灯
                        controlFillLightByDevice(true);
                    }
                } else {
                    Log.i(TAG, "开始执行 开启补光灯开启流程，本次没有开启配置，直接开启补光灯");
                    //开启补光灯
                    controlFillLightByDevice(true);
                }
            } else {
                Log.i(TAG, "开始执行 开启补光灯开启流程，本次忽略配置检测，直接开启补光灯");
                //开启补光灯
                controlFillLightByDevice(true);
            }
        } else {
            //关闭补光灯
            controlFillLightByDevice(false);
        }
    }

    /**
     * 定义一个方法用于根据当前程序所运行的设备类型来决定如何操作补光灯的开启和关闭
     *
     * @param isOpen 开启或关闭补光灯
     */
    private void controlFillLightByDevice(boolean isOpen) {
        //根据设备型号决定如何控制补光灯
        if (SystemUtils.isA33()) {                                                       //A33 设备
            //A33设备通过串口库控制
            SerialPortPublic.controlFillLight(isOpen);
        } else if (SystemUtils.isA64()) {                                                 //A64 设备
            if (SystemUtils.getTcDeviceType() == TcDeviceType.A64_VERTICAL_TOUCH_FOR_HANVON_DEVICE) {  //A64 竖屏触摸 汉王模块方案 设备
                //A64 竖屏触摸 汉王模块方案 设备 通过Gpio库控制
                TcA64GpioClient.getInstance().controlFillLight(isOpen);
            } else if (SystemUtils.getTcDeviceType() == TcDeviceType.A64_VERTICAL_TOUCH_HZ01) {  //A64 竖屏触摸 TC-Y9D-HZ01 设备
                //A64 竖屏触摸 TC-Y9D-HZ01 设备 通过Gpio库控制
                TcA64GpioClient.getInstance().controlFillLightByTc_Y9D_HZ01(isOpen);
            } else {                                                             //A64 其他机型 设备
                SerialPortPublic.controlFillLight(isOpen);
            }
        } else if (SystemUtils.isRk3399()) {                                              //rk3399 设备
            if (SystemUtils.getTcDeviceType() == TcDeviceType.RK3399_LANDSCAPE_KEY) {    //Tc-Y9D-C10B设备
                SerialPortPublic.controlFillLight(isOpen);
            } else if (SystemUtils.getTcDeviceType() == TcDeviceType.RK3399_VERTICAL_TOUCH_O8A_DOOR) {    //Tc-Y9D-O8A设备
                if (isOpen) {
                    TcRk3399GpioClient.getInstance().controlGpio(Rk3399GpioActionDefine.CONTROL_TC_Y9D_O8A_FILL_LIGHT_OPEN);
                    Log.i(TAG, "controlFillLightByDevice: 开启 Rk3399 Tc-Y9D-O8A设备 gpio补光灯");
                } else {
                    TcRk3399GpioClient.getInstance().controlGpio(Rk3399GpioActionDefine.CONTROL_TC_Y9D_O8A_FILL_LIGHT_CLOSE);
                    Log.i(TAG, "controlFillLightByDevice: 关闭 Rk3399 Tc-Y9D-O8A设备 gpio补光灯");
                }
            } else if (HardwareUtils.is20Devices()) {
                // 20D单片机设备
                SerialPortPublic.controlFillLight(isOpen);
            } else if (SystemUtils.isVankeSiteBoxDevice()){             //万科智慧工地项目 主板
                SerialPortPublic.controlFillLight(isOpen);
            } else {
                if (isOpen) {
                    TcRk3399GpioClient.getInstance().controlGpio(Rk3399GpioActionDefine.CONTROL_FILL_LIGHT_OPEN);
                    Log.i(TAG, "controlFillLightByDevice: 开启 Rk3399 设备 gpio补光灯");
                } else {
                    TcRk3399GpioClient.getInstance().controlGpio(Rk3399GpioActionDefine.CONTROL_FILL_LIGHT_CLOSE);
                    Log.i(TAG, "controlFillLightByDevice: 关闭 Rk3399 设备 gpio补光灯");
                }
            }
        } else {                                                                         //未知设备
            SerialPortPublic.controlFillLight(isOpen);
        }
    }

    /**
     * 定义一个方法用于向设备请求当前的光感值，取得后会根据配置决定是否开启补光灯
     */
    private void getLightPowerValueForOpenFillLight() {
        if (SystemUtils.isRk3399()) {
            //改变标志位为true，当获取感光值后执行开灯操作
            isOpenFillLightAfterGetLightPowerValue.set(true);
            //获取设备感光值
            SerialPortPublic.getLighrPower();
        }
    }

    /**
     * 定义一个方法用于获取 设备是否开启补光灯时间段功能配置
     *
     * @return
     */
    private boolean isOpenFillLightInTimePeriodConfig() {
        return PropertyPreference.get().getBoolean(PropertyKey.KEY_IS_OPEN_LIGHT_CONTROL_TIME_PERIOD,
                PropertyDefaultValue.DEF_CAN_OPEN_LIGHT_CONTROL);
    }

    /**
     * 定义一个方法用于获取 设备是否开启补光灯光感功能配置
     *
     * @return
     */
    private boolean isOpenFillLightInLightModuleValueConfig() {
        if (SystemUtils.isRk3399()) {
            return PropertyPreference.get().getBoolean(PropertyKey.CFG_FACE_IS_OPEN_FLASH_LIGHT,
                    PropertyDefaultValue.CFG_FACE_IS_OPEN_FLASH_LIGHT);
        } else {
            return false;
        }
    }

    /**
     * 定义一个方法用于判断能否开启补光灯
     *
     * @return
     */
    private boolean checkCanOpenFillLight() {
        //两个条件满足其一就允许开启补光灯
        if (checkFillLightInTimePeriod() || checkFillLightInLightModuleValue()) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 定义一个方法用于检测当前时间是否处于 开启补光灯时间段
     *
     * @return
     */
    private boolean checkFillLightInTimePeriod() {
        //设备必须开启灯光时间段控制功能
        if (PropertyPreference.get().getBoolean(PropertyKey.KEY_IS_OPEN_LIGHT_CONTROL_TIME_PERIOD,
                PropertyDefaultValue.DEF_CAN_OPEN_LIGHT_CONTROL)) {
            int startHour = PropertyPreference.get().getInt(PropertyKey.KEY_LIGHT_CONTROL_START_HOUR, PropertyDefaultValue.DEF_LIGHT_CONTROL_START_HOUR);
            int startMin = PropertyPreference.get().getInt(PropertyKey.KEY_LIGHT_CONTROL_START_MIN, PropertyDefaultValue.DEF_LIGHT_CONTROL_START_MIN);
            int endHour = PropertyPreference.get().getInt(PropertyKey.KEY_LIGHT_CONTROL_END_HOUR, PropertyDefaultValue.DEF_LIGHT_CONTROL_END_HOUR);
            int endMin = PropertyPreference.get().getInt(PropertyKey.KEY_LIGHT_CONTROL_END_MIN, PropertyDefaultValue.DEF_LIGHT_CONTROL_END_MIN);

            //判断当前时间是否在时间段内
            boolean isInTimeScope = LightTimeUtils.isCurrentInTimeScope(startHour, startMin, endHour, endMin);
            Log.e(TAG, "当前时间是否处于配置时间段内：  " + isInTimeScope);
            return isInTimeScope;
        } else {
            return false;
        }
    }

    /**
     * 只有rk3399设备才进行光感数值处理
     *
     * @param lightValue
     */
    public void setCurrentLightValue(int lightValue) {
        currentLightValue = lightValue;
        Log.e(TAG, "lightValueSubscription: 获取到光感数值：  " + currentLightValue);
        if (isOpenFillLightAfterGetLightPowerValue.get()) {
            //改变标志位，等待下一次执行
            isOpenFillLightAfterGetLightPowerValue.set(false);
            if (SystemUtils.isRk3399()) {
                //如果感光值在设置范围，则允许开启补光灯
                if (checkFillLightInLightModuleValue()) {
                    Log.i(TAG, "开始执行 开启补光灯开启流程，本次检测光感配置在范围内，开启补光灯");
                    TcRk3399GpioClient.getInstance().controlGpio(Rk3399GpioActionDefine.CONTROL_FILL_LIGHT_OPEN);
                } else {
                    //不在感光值的设置范围，关闭补光灯
                    Log.i(TAG, "开始执行 开启补光灯开启流程，本次检测光感配置不在范围内，关闭补光灯");
                    TcRk3399GpioClient.getInstance().controlGpio(Rk3399GpioActionDefine.CONTROL_FILL_LIGHT_CLOSE);
                }
            }

        }
    }

    /**
     * 定义一个方法用于检测当前感光值是否在 开启感光阈值控制范围内
     *
     * @return
     */
    private boolean checkFillLightInLightModuleValue() {
        //设备必须开启感光阈值控制功能
        if (PropertyPreference.get().getBoolean(PropertyKey.CFG_FACE_IS_OPEN_FLASH_LIGHT,
                PropertyDefaultValue.CFG_FACE_IS_OPEN_FLASH_LIGHT)) {
            //获取感光阈值控制范围
            int minValue = PropertyPreference.get().getInt(PropertyKey.KEY_OPEN_LIGHT_MODULE_VALUE_CONTROL_MIN_VALUE, PropertyDefaultValue.DEF_LIGHT_MODULE_VALUE_CONTROL_MIN_VALUE);
            int maxValue = PropertyPreference.get().getInt(PropertyKey.KEY_OPEN_LIGHT_MODULE_VALUE_CONTROL_MAX_VALUE, PropertyDefaultValue.DEF_LIGHT_MODULE_VALUE_CONTROL_MAX_VALUE);
            Log.e(TAG, "checkFillLightInLightModuleValue： 本次补光灯开启时的感光值为：  " + currentLightValue + " 最小开启阈值：  " + minValue
                    + "  最大开启阈值：  " + maxValue);
            if (currentLightValue >= minValue && currentLightValue <= maxValue) {        //当当前设备感光值在设定范围内时，允许开启补光灯
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    /**
     * 控制彩色灯条
     *
     * @param openIndex 需要打开灯条的序号
     */
    public void controlColorLight(int openIndex) {
        SerialPortPublic.controlColorLight(openIndex);
    }

    /**
     * 控制补光灯亮度
     *
     * @param open 是否使用pwm调光
     * @param pwm  补光灯PWM的占空比范围0~100
     */
    public void controlFillLightPwm(boolean open, int pwm) {
        // RK3399新版本设备才支持这个功能
        SerialPortPublic.controlFillLightPwm(open, pwm);
    }
}
